package com.itheima.frwameworkcache.redis;

import com.itheima.dao.PwBaseInfoDao;
import com.itheima.domain.PwBaseInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.connection.RedisListCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author sunfeng
 * @date 2021/06/02 15:02
 **/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisGEO {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PwBaseInfoDao pwBaseInfoDao;

    private final String companyGeo = "pwxkbaseinfo:locations";

    @Test
    public void testPwBaseInfo() {
        List<PwBaseInfo> pwBaseInfos =
                pwBaseInfoDao.findAll();

        for (int i = 0; i < pwBaseInfos.size(); i++) {
            PwBaseInfo pwBaseInfo = pwBaseInfos.get(i);
            try {
                redisTemplate.opsForGeo().add(companyGeo,
                        new Point(Double.parseDouble(pwBaseInfo.getLongitude()), Double.parseDouble(pwBaseInfo.getLatitude())), pwBaseInfo.getId());

            } catch (Exception e) {
                log.error("发生错误，错误信息为：{}", e.getMessage());
            }
        }
    }

    /**
     * 返回两个地方的距离，可以指定单位，比如米m，千米km，英里mi，英尺ft
     */
    @Test
    public void testDist() {
        Distance distance = redisTemplate.opsForGeo()
                .distance(companyGeo, 38367888L, 38367781L, RedisGeoCommands.DistanceUnit.KILOMETERS);
        System.out.println(distance);
    }


    /**
     *从键里面返回所有给定位置元素的位置（经度和纬度）。
     */
    @Test
    public void testPos() {
        List<RedisListCommands.Position> position = redisTemplate.opsForGeo().position(companyGeo, 38367888L, 38367781L);

        System.out.println(position);
    }

    @Test
    public void testGeoHash() {
        List<String> results = redisTemplate.opsForGeo()
                .hash(companyGeo, 38329773L, 38329730L, 38329696L);
        System.out.println(results);
    }

    /**
     * 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素。
     * 范围可以使用以下其中一个单位：m 表示单位为米。km 表示单位为千米。mi 表示单位为英里。ft 表示单位为英尺。
     */
    @Test
    public void testPwBaseInfoRadio() {
        Long startTime = System.currentTimeMillis();
        Distance distance = new Distance(5, Metrics.KILOMETERS);
        Circle circle = new Circle(new Point(122.03018, 36.97091), distance);


        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands
                .GeoRadiusCommandArgs
                .newGeoRadiusArgs()
                .includeDistance()
                .includeCoordinates()
                .sortAscending().limit(150);
        GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo()
                .radius(companyGeo, circle, args);

        print(results);
    }

    /**
     * 根据member （名称 最好使用唯一标识）   查询周边最近的地点
     */
    @Test
    public void testNearByPlace() {
        Distance distance = new Distance(5, Metrics.KILOMETERS);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo()
                .radius(companyGeo, 38329773L, distance, args);
        print(results);
    }



    private void print(GeoResults<RedisGeoCommands.GeoLocation<String>> results) {
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = results.getContent();
        content.forEach(geoLocationGeoResult -> {
            System.out.println(geoLocationGeoResult.getContent());

        });
    }
}
